#!/usr/bin/env python2
#-*- coding: utf-8 -*-

import os
import re
import json
import logging
import time
import traceback
import threading

from Ump import utils, defs
from Ump.common import log
from Ump.common import exception
from Ump.common.config_base import ConfigManager

from Ump.objs.db import models
from Ump.objs.manager_base import Manager
from Ump.objs.session_wrapper import enable_log_and_session, _sw


LOG = log.get_log('Ump.objs.rrserver.manager')

remotecopy_config = ConfigManager(defs.REMOTECOPY_CLIENT_CONFIG_PATH)


class ConfigBase(object):

    def make_remotecopy_cfg(self, rrservers, rrclient, vip):
        rrserver = rrservers
        if not rrservers:
            raise exception.NotFound(rrservers=rrservers)

        cluster = models.Cluster.query.first()
	if cluster.hosts:
            vip_password = cluster.hosts[0].passwd
        global_kw = {
            'stor': 'root:%s@%s' % (vip_password, vip),
        }
        remotecopy_config.set_option('global', **global_kw)

        servers = [x.address for x in rrservers]
	port = rrservers[0].port if rrservers else ''
        client_kw = {
            'server': ",".join(map(lambda x: "%s:%s" % (x, port), servers)),
            'volume': "%s@%s" % (rrclient.src_volume_path, rrclient.dst_volume_path),
            "interval": rrclient.interval,
            "qos": rrclient.qos,
        }

        remotecopy_config.set_option(rrclient.name, **client_kw)

        return rrclient 

    def _get_cluster_vip(self, cluster_id=1):
        cluster = _sw.db_cluster(cluster_id)
        if not cluster:
            raise exception.NotFound(cluster_id=cluster_id)

        vip = cluster.vip
        if not vip.strip():
            raise exception.NotFound(vip='')
            
        return vip


@models.add_model(models.RRServer)
class RRServerManager(Manager, ConfigBase):

    def __init__(self):
        self.super_ = super(RRServerManager, self)
        self.super_.__init__()

    @enable_log_and_session(resource='site', event='create')
    def create(self, _logger, kwargs):
        address = kwargs['address']
        if models.RRServer.query.filter_by(address=address).first():
            raise exception.AlreadyExists(address=address)

        _logger.update_props(oplog_obj=address,  user_id=kwargs.get('op_user_id'))

        rrserver = self._create(**kwargs)
        return rrserver
            
    def _create(self, address, port, username='admin', **kwargs):
        values = {
            'address': address,
            'port': port,
            'user_id': _sw.get_user_id(username),
            'user': username,
        }
        rrserver = models.RRServer(values).save()
        return rrserver 

    @enable_log_and_session(resource='site', event='update')
    def update(self, _logger, kwargs):
        s_id = kwargs.get('id')
        rrserver = self._get_one(s_id)

        _logger.update_props(oplog_obj=rrserver.address,  user_id=kwargs.get('op_user_id'))

        vip = self._get_cluster_vip()
        rrserver = self._update(rrserver, **kwargs)

        for x in rrserver.rrclients:
            self.make_remotecopy_cfg(x.rrservers, x, vip)

        return rrserver

    def _update(self, rrserver, address, port, username='admin', **kwargs):

        values = {
            'address': address,
            'port': port,
            'user_id': _sw.get_user_id(username),
            'user': username,
        }

        rrserver.update(values)
        return rrserver 

    @enable_log_and_session(resource='site', event='delete')
    def delete(self, _logger, kwargs):
        s_id = kwargs.get('id')
        rrserver = self._get_one(s_id)

        if rrserver.rrclients:
            raise exception.SiteNotEmpty(id=s_id)

        _logger.update_props(oplog_obj=rrserver.address,  user_id=kwargs.get('op_user_id'))
        
        return rrserver.delete()

    def _get_one(self, s_id):
        rrserver = _sw.get_one(models.RRServer, id_or_spec=s_id)
        if not rrserver:
            raise exception.NotFound(s_id=s_id)
        return rrserver


@models.add_model(models.RRClient)
class RRClientManager(Manager, ConfigBase):

    def __init__(self):
        self.super_ = super(RRClientManager, self)
        self.super_.__init__()

    def _check_src_volume_path(self, src_volume_path, rrclient_id=-1):
        rrclient = models.RRClient.query.filter_by(src_volume_path=src_volume_path).first()
        if rrclient and rrclient.id != rrclient_id:
            raise exception.AlreadyExistsPath(src_volume_path)

    @enable_log_and_session(resource='relationships', event='create')
    def create(self, _logger, kwargs):
        src_volume_path = kwargs['src_volume_path']
        dst_volume_path = kwargs['dst_volume_path']
        name = kwargs['name']
        
        detail = 'Source:%s; Destination:%s' % (src_volume_path, dst_volume_path)
        _logger.update_props(oplog_obj=name, detail=detail)

        rrclient = self._create(**kwargs)
        return rrclient
            
    def _create(self, name, src_volume_path, dst_volume_path, site_ids, username='admin', **kwargs):
        rrservers = _sw.get_list_by_ids(models.RRServer, site_ids)
        qos = int(kwargs.get('qos')) if kwargs.get('qos')  else None

        self._check_src_volume_path(src_volume_path)

        values = {
            "name": name,
            "src_volume_path": src_volume_path,
            "dst_volume_path": dst_volume_path,
            "interval": kwargs.get('interval'),
            "qos": qos,
            "user_id": _sw.get_user_id(username),
            "rrservers": rrservers,
            'user': username,
        }
        vip = self._get_cluster_vip()
        rrclient = models.RRClient(values).save()
        
        self.make_remotecopy_cfg(rrservers, rrclient, vip)
        
        return rrclient 

    @enable_log_and_session(resource='relationships', event='update')
    def update(self, _logger, kwargs):
        s_id = kwargs.get('id')
        rrclient = self._get_one(s_id)

        _logger.update_props(oplog_obj=rrclient.name)

        rrclient = self._update(rrclient, **kwargs)
        return rrclient

    def _update(self, rrclient, name=None, src_volume_path=None, 
                    dst_volume_path=None, site_ids=None, username='admin', **kwargs):
        qos = int(kwargs.get('qos')) if kwargs.get('qos')  else None

        self._check_src_volume_path(src_volume_path, rrclient.id)

        values = dict()
        utils.update_values(values, 'name', name)
        utils.update_values(values, "src_volume_path", src_volume_path)
        utils.update_values(values, "dst_volume_path", dst_volume_path)
        utils.update_values(values, "interval", kwargs.get('interval'))
        utils.update_values(values, "qos", qos)

        rrservers = _sw.get_list_by_ids(models.RRServer, site_ids)
        utils.update_values(values, 'rrservers', rrservers, is_list=True)

        vip = self._get_cluster_vip()

        rrclient.update(values) 

        self.make_remotecopy_cfg(rrservers, rrclient, vip)
        return rrclient 

    @enable_log_and_session(resource='relationships', event='delete')
    def delete(self, _logger, kwargs):
        s_id = kwargs.get('id')
        rrclient = self._get_one(s_id)

        _logger.update_props(oplog_obj=rrclient.name)

        remotecopy_config.remove_section(rrclient.name)
        
        return rrclient.delete()

    def _get_one(self, s_id):
        rrclient = _sw.get_one(models.RRClient, id_or_spec=s_id)
        if not rrclient:
            raise exception.NotFound(s_id=s_id)
        return rrclient


if __name__ == '__main__':
    snm = RRServerManager()
